package com.cloud.oss.minio;

import com.cloud.oss.minio.config.MinioConfigurationProperties;
import com.cloud.oss.minio.exception.MinioException;
import com.cloud.oss.minio.util.SnowflakeIdWorker;
import io.minio.MinioClient;
import io.minio.PutObjectOptions;
import io.minio.errors.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * @author wangjian
 * @version 1.0.0
 * @create 2020年11月11日 14:47
 * @since JDK 1.8
 * Life is so short,do something to make yourself happy,such as coding
 */
@Service
public class MinioService {

    @Autowired
    private MinioClient minioClient;

    @Autowired
    private MinioConfigurationProperties configurationProperties;

    /**
     * 下载文件
     *
     * @param fileKey
     * @return
     * @throws MinioException
     */
    public InputStream download(String fileKey) throws MinioException {
        try {
            return minioClient.getObject(configurationProperties.getBucket(), fileKey);
        } catch (XmlParserException | InvalidBucketNameException | NoSuchAlgorithmException | InsufficientDataException | IOException | InvalidKeyException | ErrorResponseException | InternalException | InvalidResponseException e) {
            throw new MinioException("Error while Download files in Minio", e);
        }
    }

    /**
     * 上传文件
     *
     * @param file
     * @return 基于雪花算法生成唯一id + 后缀名
     * @throws MinioException
     */
    public String upload(MultipartFile file) throws MinioException {
        String originalFilename = file.getOriginalFilename();
        if (StringUtils.isEmpty(originalFilename)) {
            throw new MinioException("Original File Name Is Not Empty");
        }
        //获取最后一个.的位置
        int lastIndexOf = originalFilename.lastIndexOf(".");
        //获取文件的后缀名 .jpg
        String suffix = originalFilename.substring(lastIndexOf);
        //雪花算法生成唯一id
        String fileKey = SnowflakeIdWorker.generateId() + suffix;

        this.minIoClientPutFille(file, fileKey);
        return fileKey;
    }

    /**
     * 上传inputStream文件
     *
     * @param inputStream
     * @param suffix      文件后缀 （.png）
     * @return 基于雪花算法生成唯一id + 后缀名
     * @throws MinioException
     */
    public String uploadByInputStream(InputStream inputStream, String suffix) throws MinioException {
        if (StringUtils.isEmpty(suffix)) {
            throw new MinioException("suffix Is Not Empty");
        }
        //雪花算法生成唯一id
        String fileKey = SnowflakeIdWorker.generateId() + suffix;

        this.minIoClientPutInputStream(inputStream, fileKey);
        return fileKey;
    }

    /**
     * 覆盖类型上传
     *
     * @param file
     * @param fileKey 通过上传返回文件标示，必须携带文件类型后缀
     * @return fileKey
     * @throws MinioException
     */
    public String upload(MultipartFile file, String fileKey) throws MinioException {
        if (StringUtils.isEmpty(fileKey)) {
            throw new MinioException("fileKey Is Not Empty");
        } else {
            //获取最后一个.的位置
            int lastIndexOf = fileKey.lastIndexOf(".");
            if (lastIndexOf <= 0) {
                throw new MinioException("fileKey Is must hava suffix");
            }
            this.minIoClientPutFille(file, fileKey);
            return fileKey;
        }
    }

    private void minIoClientPutFille(MultipartFile file, String fileKey) throws MinioException {
        try {
            InputStream inputStream = file.getInputStream();
            minIoClientPutInputStream(inputStream, fileKey);
        } catch (IOException ioException) {
            throw new MinioException("Error while upload files in Minio", ioException);
        }
    }

    private void minIoClientPutInputStream(InputStream inputStream, String fileKey) throws MinioException {
        try {
            this.minioClient.putObject(this.configurationProperties.getBucket(), fileKey, inputStream, new PutObjectOptions((long) inputStream.available(), -1L));
        } catch (IOException | ErrorResponseException | InsufficientDataException | InternalException | InvalidBucketNameException | InvalidKeyException | NoSuchAlgorithmException | XmlParserException | InvalidResponseException var4) {
            throw new MinioException("Error while upload files in Minio", var4);
        }
    }

}
